<template>
  <el-form
    class="edit-report-template-filter third-party-dlg"
    ref="form"
    :model="formData"
    :rules="rules"
    label-width="92px"
    :size="formItemSize"
    @submit.prevent
  >
    <el-form-item label="过滤字段" prop="paramName">
      <el-cascader
        v-model="formData.paramPath"
        :options="dialogParams.columnList"
        :props="{ label: 'name', value: 'id' }"
        size="default"
        style="width: 100%"
        @change="onFilterColumnChange"
      >
        <template v-slot="{ data }">
          <el-row type="flex" justify="space-between" align="middle">
            <span>{{ data.name }}</span>
            <el-tag v-if="data.dictId != null" size="default" style="margin-left: 20px"
              >字典</el-tag
            >
          </el-row>
        </template>
      </el-cascader>
    </el-form-item>
    <el-form-item label="是否必填" required>
      <el-switch v-model="formData.required" />
    </el-form-item>
    <el-form-item label="过滤规则" prop="filterType">
      <el-select v-model="formData.filterType" size="default" @change="onFilterTypeChange">
        <el-option
          v-for="item in getValidCriteriaFilterType"
          :key="item.id"
          :label="item.name"
          :value="item.id"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="过滤值类型" prop="filterValueType">
      <el-select
        v-model="formData.filterValueType"
        size="default"
        placeholder=""
        :disabled="!needFilterValue"
        @change="onFilterValueTypeChange"
      >
        <el-option
          v-for="item in getValidFilteValueType"
          :key="item"
          :label="FilterValueKind.getValue(item)"
          :value="item"
        />
      </el-select>
    </el-form-item>
    <!-- 参数值 -->
    <!-- 表单输入参数 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.FORM_PARAM"
      label="过滤值"
      :prop="needFilterValue ? 'paramValue' : undefined"
      :disabled="!needFilterValue"
    >
      <el-select v-model="formData.paramValue" size="default" clearable placeholder="">
        <el-option
          v-for="name in dialogParams.formParamList"
          :key="name"
          :label="name"
          :value="name"
        />
      </el-select>
    </el-form-item>
    <!-- 组件数据参数 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.WIDGET_DATA"
      label="过滤组件"
      :prop="needFilterValue ? 'formWidgetId' : undefined"
      :disabled="!needFilterValue"
    >
      <el-select
        v-model="formData.formWidgetId"
        key="formWidgetId"
        size="default"
        clearable
        placeholder=""
        @change="formData.formWidgetColumn = undefined"
      >
        <el-option
          v-for="widget in (dialogParams.widgetList || []).filter(widget =>
            formData.filterType === CriteriaFilterType.BETWEEN
              ? widget.widgetType === SysCustomWidgetType.DateRange
              : widget.widgetType !== SysCustomWidgetType.DateRange,
          )"
          :key="widget.widgetId"
          :label="widget.showName"
          :value="widget.widgetId"
        />
      </el-select>
    </el-form-item>
    <el-form-item
      v-if="
        formData.filterValueType === FilterValueKind.WIDGET_DATA &&
        getFilterWidget != null &&
        Array.isArray(getFilterWidget.children) &&
        getFilterWidget.children.length > 0
      "
      label="组件字段"
      :prop="needFilterValue ? 'formWidgetColumn' : undefined"
      :disabled="!needFilterValue"
    >
      <el-select
        v-model="formData.formWidgetColumn"
        key="formWidgetColumn"
        size="default"
        clearable
        placeholder=""
      >
        <el-option
          v-for="column in (getFilterWidget || {}).children"
          :key="column.id"
          :label="column.showName"
          :value="column.id"
        />
      </el-select>
    </el-form-item>
    <!-- 字典参数 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.DICT_DATA"
      label="过滤值字典"
      :prop="needFilterValue ? 'paramDictId' : undefined"
      :disabled="!needFilterValue"
    >
      <el-row type="flex">
        <el-select
          v-model="formData.paramDictId"
          key="paramDictId"
          style="width: 200px; flex-grow: 1"
          size="default"
          clearable
          placeholder=""
          :disabled="getFilterColumn == null || getFilterColumn.dictId != null"
          @change="formData.paramValue = undefined"
        >
          <el-option
            v-for="dict in getValidDictList"
            :key="dict.id"
            :label="dict.name"
            :value="dict.id"
            :disabled="dict.disabled"
          />
        </el-select>
        <span
          v-if="(getFilterColumn || {}).dictId != null"
          style="margin-left: 15px; color: #e6a23c; flex-grow: 0"
          >只显示字段绑定字典</span
        >
      </el-row>
    </el-form-item>
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.DICT_DATA"
      label="字典数据"
      :prop="needFilterValue ? 'paramValue' : undefined"
      :disabled="!needFilterValue"
    >
      <el-select
        v-model="formData.paramValue"
        size="default"
        clearable
        placeholder=""
        :multiple="
          formData.filterType === CriteriaFilterType.IN ||
          formData.filterType === CriteriaFilterType.NOT_IN
        "
      >
        <el-option
          v-for="data in paramDictDataList"
          :key="data.id"
          :label="data.name"
          :value="data.id"
        />
      </el-select>
    </el-form-item>
    <!-- 字段参数 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.COLUMN_DATA"
      label="参数值"
      :prop="needFilterValue ? 'paramValue' : undefined"
      :disabled="!needFilterValue"
    >
      <el-select
        v-model="formData.paramValue"
        size="default"
        clearable
        placeholder=""
        :multiple="
          formData.filterType === CriteriaFilterType.IN ||
          formData.filterType === CriteriaFilterType.NOT_IN
        "
      >
        <el-option
          v-for="data in (getFilterColumn || {}).columnDataList"
          :key="data.id"
          :label="data.name"
          :value="data.id"
        />
      </el-select>
    </el-form-item>
    <!-- 打印模版输入参数 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.PRINT_INPUT_PARAM"
      label="过滤值"
      :prop="needFilterValue ? 'paramValue' : undefined"
    >
      <el-select
        v-model="formData.paramValue"
        size="default"
        clearable
        placeholder=""
        :disabled="!needFilterValue"
      >
        <el-option
          v-for="name in dialogParams.formParamList"
          :key="name"
          :label="name"
          :value="name"
        />
      </el-select>
    </el-form-item>
    <!-- 内置变量 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.INNER_VARIABLE"
      label="过滤值"
      :prop="needFilterValue ? 'paramValue' : undefined"
    >
      <el-select
        v-model="formData.paramValue"
        size="default"
        clearable
        placeholder=""
        :disabled="!needFilterValue"
      >
        <el-option
          v-for="item in CustomDateValueType.getList()"
          :key="item.id"
          :label="item.name"
          :value="item.id"
        />
      </el-select>
    </el-form-item>
    <!-- 自定义参数 -->
    <el-form-item
      v-if="formData.filterValueType === FilterValueKind.INPUT_DATA"
      label="过滤值"
      :prop="needFilterValue ? 'paramValue' : undefined"
    >
      <!-- 数字类型字段 -->
      <el-input-number
        v-if="
          getFilterColumn != null &&
          ['Integer', 'Long', 'Double', 'BigDecimal'].indexOf(getFilterColumn.fieldType) !== -1
        "
        v-model="formData.paramValue"
        controls-position="right"
        size="default"
        placeholder=""
        :disabled="!needFilterValue"
      />
      <!-- Boolean类型字段 -->
      <el-switch
        v-else-if="getFilterColumn != null && getFilterColumn.fieldType === 'Boolean'"
        v-model="formData.paramValue"
        size="default"
        :disabled="!needFilterValue"
      />
      <!-- 日期类型字段 -->
      <el-date-picker
        v-else-if="getFilterColumn != null && getFilterColumn.fieldType === 'Date'"
        v-model="formData.paramValue"
        type="datetime"
        size="default"
        format="YYYY-MM-DD HH:mm:ss"
        value-format="YYYY-MM-DD HH:mm:ss"
        :disabled="!needFilterValue"
      >
      </el-date-picker>
      <!-- 字符串类型字段 -->
      <el-input
        v-else
        :disabled="!needFilterValue"
        v-model="formData.paramValue"
        size="default"
        placeholder=""
        clearable
      />
    </el-form-item>
    <el-row type="flex" justify="end" class="dialog-btn-layer menu-box" style="margin-top: 15px">
      <el-button :size="formItemSize" :plain="true" @click="onCancel"> 取消 </el-button>
      <el-button type="primary" :size="formItemSize" @click="onSubmit"> 确定 </el-button>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
import { CascaderValue } from 'element-plus';
import { ANY_OBJECT } from '@/types/generic';
import {
  getFilterTypeByFieldType,
  getValidFilterValueTypeByFieldType,
} from '@/components/Charts/utils';
import { ReportDatasetController, ReportDictController } from '@/api/report';
import { findItemFromList } from '@/common/utils';
import {
  FilterValueKind,
  CriteriaFilterType,
  CustomDateValueType,
} from '@/common/staticDict/report';
import { SysCustomWidgetType } from '@/common/staticDict/index';
import { DialogProp } from '@/components/Dialog/types';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
const layoutStore = useLayoutStore();

interface IProps extends ThirdProps {
  rowData?: ANY_OBJECT;
  columnList: ANY_OBJECT[];
  // 打印模版输入参数 / 表单输入参数
  formParamList: ANY_OBJECT[];
  // 报表字典列表
  reportDictList: ANY_OBJECT[];
  // 组件列表
  widgetList: ANY_OBJECT[];
  // 可用的过滤值类型
  validFilterValueType: number[];
  // 当使用Dialog.show弹出组件时，须定义该prop属性，以便对dialog进行回调
  dialog?: DialogProp<ANY_OBJECT | ANY_OBJECT[] | undefined>;
}
const props = defineProps<IProps>();
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const formItemSize = computed(() => {
  return layoutStore.defaultFormItemSize || thirdParams.value.defaultFormItemSize?.value;
});

const form = ref();
const formData = ref<ANY_OBJECT>({
  paramId: undefined,
  paramName: undefined,
  required: false,
  filterType: undefined,
  filterValueType: FilterValueKind.INPUT_DATA,
  // 字典过滤
  paramDictId: undefined,
  // 表单组件参数
  formWidgetId: undefined,
  formWidgetColumn: undefined,
  // 参数值
  paramValue: undefined,
  relationId: undefined,
  paramPath: [],
});
// 字典数据值
const paramDictDataList = ref<ANY_OBJECT[]>([]);
const rules = {
  paramName: [{ required: true, message: '过滤字段不能为空', trigger: 'blur' }],
  filterType: [{ required: true, message: '过滤规则不能为空', trigger: 'blur' }],
  filterValueType: [{ required: true, message: '过滤值类型不能为空', trigger: 'blur' }],
  paramDictId: [{ required: true, message: '过滤值字典不能为空', trigger: 'blur' }],
  formWidgetId: [{ required: true, message: '过滤组件不能为空', trigger: 'blur' }],
  formWidgetColumn: [{ required: true, message: '过滤组件字段不能为空', trigger: 'blur' }],
  paramValue: [{ required: true, message: '过滤值不能为空', trigger: 'blur' }],
};

const dialogParams = computed<ANY_OBJECT>(() => {
  return {
    rowData: props.rowData || thirdParams.value.rowData,
    columnList: props.columnList || thirdParams.value.columnList || [],
    formParamList: props.formParamList || thirdParams.value.formParamList || [],
    reportDictList: props.reportDictList || thirdParams.value.reportDictList || [],
    widgetList: props.widgetList || thirdParams.value.widgetList || [],
    validFilterValueType:
      props.validFilterValueType || thirdParams.value.validFilterValueType || [],
  };
});
const needFilterValue = computed(() => {
  return (
    formData.value.filterType !== CriteriaFilterType.NOT_NULL &&
    formData.value.filterType !== CriteriaFilterType.IS_NULL
  );
});
const getFilterColumn = computed(() => {
  if (formData.value.relationId == null) {
    // 绑定主数据集字段
    return findItemFromList(dialogParams.value.columnList, formData.value.paramName, 'id');
  } else {
    // 绑定关联数据集字段
    let relation = findItemFromList(dialogParams.value.columnList, formData.value.relationId, 'id');
    if (relation != null) {
      return findItemFromList(relation.children, formData.value.paramName, 'id');
    }
  }

  return null;
});
const getValidCriteriaFilterType = computed(() => {
  let column = getFilterColumn.value;
  if (column == null) return [];
  let temp = getFilterTypeByFieldType(column.fieldType);
  return temp;
});
const getValidFilteValueType = computed(() => {
  let column = getFilterColumn.value;
  if (column == null) return dialogParams.value.validFilterValueType;
  let tempList = getValidFilterValueTypeByFieldType(
    dialogParams.value.validFilterValueType,
    formData.value.filterType,
    column,
  );
  // between类型只支持过滤组件
  if (formData.value.filterType === CriteriaFilterType.BETWEEN) {
    tempList = tempList.filter(item => item === FilterValueKind.WIDGET_DATA);
  }

  return tempList;
});
const getValidDictList = computed<ANY_OBJECT[]>(() => {
  if (getFilterColumn.value == null) return [] as ANY_OBJECT[];
  return (
    dialogParams.value.reportDictList.map((item: ANY_OBJECT) => {
      return {
        ...item,
        // disabled: getFilterColumn.value.dictId == null ? false : (item.id !== getFilterColumn.value.dictId),
        dictDataList: item.dictDataList,
      } as ANY_OBJECT;
    }) || ([] as ANY_OBJECT[])
  );
});
const getFilterValueDict = computed(() => {
  for (let i = 0; i < getValidDictList.value.length; i++) {
    if (formData.value.paramDictId === getValidDictList.value[i].id)
      return getValidDictList.value[i];
  }

  return null;
});
const getFilterWidget = computed(() => {
  return findItemFromList(dialogParams.value.widgetList, formData.value.formWidgetId, 'widgetId');
});

const onCancel = () => {
  if (props.dialog) {
    props.dialog.cancel();
  } else {
    onCloseThirdDialog(false);
  }
};
const onSubmit = () => {
  form.value.validate((valid: boolean) => {
    if (!valid) return;
    if (props.dialog) {
      props.dialog.submit(formData.value);
    } else {
      onCloseThirdDialog(true, dialogParams.value.rowData, formData.value);
    }
  });
};
const onFilterValueTypeChange = () => {
  formData.value.formInputParam = undefined;
  formData.value.reportPrintVariable = undefined;
  formData.value.customParam = undefined;
  formData.value.paramDictId = (getFilterColumn.value || {}).dictId;
  formData.value.paramDictData = undefined;
  formData.value.paramColumnData = undefined;
  formData.value.innerVeriable = undefined;
  formData.value.paramValue = undefined;
  formData.value.formWidgetId = undefined;
  formData.value.formWidgetColumn = undefined;
};
const onFilterTypeChange = (val: number) => {
  if (val === CriteriaFilterType.IN || val === CriteriaFilterType.NOT_IN) {
    formData.value.filterValueType = FilterValueKind.DICT_DATA;
  } else if (val === CriteriaFilterType.BETWEEN) {
    formData.value.filterValueType = FilterValueKind.WIDGET_DATA;
  } else {
    formData.value.filterValueType = FilterValueKind.INPUT_DATA;
  }
  onFilterValueTypeChange();
};
const onFilterColumnChange = (val: CascaderValue) => {
  formData.value.filterType = CriteriaFilterType.EQ;
  formData.value.required = false;
  formData.value.relationId = undefined;
  if (Array.isArray(val) && val.length > 0) {
    formData.value.paramName = val[val.length - 1];
    if (val.length === 2) {
      formData.value.relationId = val[0];
    }
  } else {
    formData.value.paramName = undefined;
  }
  onFilterTypeChange(CriteriaFilterType.EQ);
};
const listDictData = (dictId: number) => {
  return new Promise<ANY_OBJECT[]>((resolve, reject) => {
    ReportDictController.listDictData({
      dictId: dictId,
    })
      .then(res => {
        resolve(res.data);
      })
      .catch(e => {
        reject(e);
      });
  });
};
const listColumnData = (datasetId: string, columnId: string) => {
  return new Promise<ANY_OBJECT[]>((resolve, reject) => {
    ReportDatasetController.listDataWithColumn({
      datasetId: datasetId,
      columnId: columnId,
    })
      .then(res => {
        resolve(res.data);
      })
      .catch(e => {
        reject(e);
      });
  });
};
const loadReportDictDataList = (node: ANY_OBJECT | null) => {
  if (node == null || Array.isArray(node.dictDataList)) {
    paramDictDataList.value = (node || {}).dictDataList;
    return;
  }
  listDictData(node.id)
    .then(dataList => {
      paramDictDataList.value = dataList;
      node.dictDataList = dataList;
    })
    .catch(e => {
      console.warn(e);
    });
};
const loadColumnDataList = () => {
  if (getFilterColumn.value == null) return;
  if (Array.isArray(getFilterColumn.value.columnDataList)) return;
  listColumnData(getFilterColumn.value.datasetId, getFilterColumn.value.columnId)
    .then(dataList => {
      let columnName = getFilterColumn.value?.columnName;
      if (getFilterColumn.value) {
        getFilterColumn.value.columnDataList = dataList.map(item => {
          if (item[columnName + '__DictMap'] != null) {
            return {
              ...item[columnName + '__DictMap'],
            };
          } else {
            return {
              id: item[columnName],
              name: item[columnName],
            };
          }
        });
      }
    })
    .catch(e => {
      console.warn(e);
    });
};

watch(
  () => getFilterValueDict.value,
  newValue => {
    loadReportDictDataList(newValue);
  },
  {
    immediate: true,
  },
);
watch(
  () => getFilterColumn.value,
  () => {
    loadColumnDataList();
  },
  {
    immediate: true,
  },
);

onMounted(() => {
  if (dialogParams.value.rowData != null) {
    formData.value = {
      ...formData.value,
      ...dialogParams.value.rowData,
    };

    formData.value.paramPath =
      formData.value.relationId == null
        ? [formData.value.paramName]
        : [formData.value.relationId, formData.value.paramName];
    loadReportDictDataList(getFilterValueDict.value);
    loadColumnDataList();
  } else {
    formData.value.paramId = new Date().getTime();
  }
});
</script>
